import type { ITestPaper, ITestPaperBaseData } from '../test-paper'
import type { ITestLoader } from './type'
import type { ITestItem } from '../test-item'
import { createTestPaper } from '../test-paper'
import { createTestItem } from '../test-item'
import localforage from 'localforage'

const paperBaseStore = localforage.createInstance({ name: "paperBaseStore" })

interface ISourcePaperItems {
    [category: string]: ITestItem[]
}

interface ISourcePaperData {
    name: string
    description: string
    lastModified: string
    "test-items": ISourcePaperItems
}

export function createPaperStorageName(paperName: string) {
    return `paperItemStore-${paperName}`
}

// 获取资源数据
async function getSourceData(apiUrl: string): Promise<ISourcePaperData[]> {
    const response = await fetch(apiUrl + "/index.json?=" + Date.now())
    const names: string[] = await response.json()
    const sourcePapersData = await Promise.all(
        names.map(async (name) => {
            const response = await fetch(apiUrl + "/" + name + ".json?=" + Date.now())
            const lastModified = response.headers.get("last-modified")
            const sourcePaperData = await response.json()
            return { ...sourcePaperData, lastModified }

        })
    )
    return sourcePapersData
}

// 资源数据入库
async function sourceDataToStorage(sourcePaperDataList: ISourcePaperData[]) {

    for (const sourcePaperData of sourcePaperDataList) {
        const { name, description, lastModified, "test-items": sourcePaperItems } = sourcePaperData
        const paperBaseData = (await paperBaseStore.getItem(name)) as Omit<ISourcePaperData, "test-items"> | null
        if (paperBaseData === null || paperBaseData.lastModified !== lastModified) {
            await paperBaseStore.setItem(name, { name, description, lastModified })
            await testItemsToStorage(sourcePaperItems, name)
        }
    }
}

// 试题入库
async function testItemsToStorage(sourcePaperItems: ISourcePaperItems, paperName: string) {

    let sortId = 0

    // 数据库试题列表
    const storeTestItems: { [id: string]: ITestItem } = {}
    const paperItemStore = localforage.createInstance({ name: createPaperStorageName(paperName) })
    await paperItemStore.iterate((item: ITestItem) => { storeTestItems[item.id] = item })
    await paperItemStore.clear()

    // 待入库的试题列表
    const sourceItemList: { [id: string]: ITestItem } = {}
    for (const [category, items] of Object.entries(sourcePaperItems)) {
        items.forEach(item => {
            item.sortId = sortId++
            item.paperName = paperName
            item.category = category
            item.lastTime = new Date("1970-1-1").getTime()

            if (item.id in storeTestItems) {
                item.lastTime = storeTestItems[item.id].lastTime
                item.level = storeTestItems[item.id].level
            }

            sourceItemList[item.id] = item
        })
    }


    // 全部入库
    await Promise.all(
        Object.values(sourceItemList).map(async (item) => {
            await paperItemStore.setItem(item.id, item)
        })
    )
}


export class TestLoaderCloudStorage implements ITestLoader {

    constructor(
        public apiUrl: string
    ) { }

    async testSync() {
        const sourcePaperDataList = await getSourceData(this.apiUrl)
        await sourceDataToStorage(sourcePaperDataList)
    }

    // 载入试卷基础信息列表
    async loadPaperBaseDataList(): Promise<ITestPaperBaseData[]> {

        let paperBaseDataList: ITestPaperBaseData[] = []

        try {

            // 获取题库基础信息列表
            await paperBaseStore.iterate((value) => { paperBaseDataList.push(value as ITestPaperBaseData) })
        } catch (error) {
            console.log(error)
            throw error
        }
        return paperBaseDataList
    }

    // 获取试卷
    async loadPaper(paperName: string): Promise<ITestPaper> {

        // 获取试卷基础信息
        const paperBaseData = (await paperBaseStore.getItem(paperName)) as Omit<ISourcePaperData, "test-items"> | null

        if (paperBaseData === null) throw new Error("试卷不存在")

        // 提取试卷名、试卷描述
        const { name, description } = paperBaseData as Omit<ISourcePaperData, "test-items">

        // 获取题库存储对象
        const paperItemStore = localforage.createInstance({ name: createPaperStorageName(name) })

        // 创建试卷对象
        const paper = createTestPaper(paperName, description, [])

        // 从题库存储对象中找出试题，创建试题对象，并添加到试卷对象中
        await paperItemStore.iterate((item: ITestItem) => {
            const testItem = createTestItem(item.id, item.title, item.content, item.level, item.paperName, item.category, item.lastTime, item.sortId)
            paper.addTestItem(testItem)
        })

        paper.items.sort((a, b) => a.sortId - b.sortId)

        return paper
    }

    // 删除试卷
    async removePaper(paperName: string) {

        // 删除试卷基础信息
        await paperBaseStore.removeItem(paperName)

        // 删除试题数据库
        await localforage.dropInstance({ name: createPaperStorageName(paperName) })

    }
}

export function createTestLoaderCloudStorage(apiUrl: string): TestLoaderCloudStorage {
    return new TestLoaderCloudStorage(apiUrl)
}